package Connectivity;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import Command.LDrawPart;
import Common.Box3;
import Common.Matrix4;
import Common.Vector3f;
import LDraw.Files.LDrawFile;
import LDraw.Files.LDrawModel;
import LDraw.Files.LDrawStep;
import LDraw.Support.ConnectivityLibrary;
import LDraw.Support.DispatchGroup;
import LDraw.Support.LDrawDirective;
import LDraw.Support.LDrawPaths;
import LDraw.Support.LDrawUtilities;
import LDraw.Support.MatrixMath;
import LDraw.Support.PartLibrary;
import Window.MOCBuilder;
public class Custom2dFieldGenerator {
enum HoleTypeT {
Hole_Rect, Hole_Circle;
private int width = 0;
private int height = 0;
public int getHeight() {
return this.height;
}
public int getWidth() {
return this.width;
}
public void setSize(int width, int height) {
this.width = width;
this.height = height;
}
}
enum StudTypeT {
Stud, Stud_RoundingBottom
}
private static Custom2dFieldGenerator _instance = null;
public synchronized static Custom2dFieldGenerator getInstance() {
if (_instance == null)
_instance = new Custom2dFieldGenerator();
return _instance;
}
// public static void main(String args[]) {
// String partName = "54200.dat";
//
// Custom2dFieldGenerator.getInstance().getHoleInfo(partName);
// Custom2dFieldGenerator.getInstance().deleteConnFile(partName);
// }
private HashMap<String, ArrayList<HoleTypeT>> holeCandidatePartNameMap;
private HashMap<String, ArrayList<StudTypeT>> studCandidatePartNameMap;
private Custom2dFieldGenerator() {
holeCandidatePartNameMap = new HashMap<String, ArrayList<HoleTypeT>>();
studCandidatePartNameMap = new HashMap<String, ArrayList<StudTypeT>>();
holeCandidatePartNameMap.put("box5.dat", new ArrayList<HoleTypeT>());
holeCandidatePartNameMap.get("box5.dat").add(HoleTypeT.Hole_Rect);
holeCandidatePartNameMap.put("box4.dat", new ArrayList<HoleTypeT>());
holeCandidatePartNameMap.get("box4.dat").add(HoleTypeT.Hole_Rect);
holeCandidatePartNameMap.put("box4-1.dat", new ArrayList<HoleTypeT>());
holeCandidatePartNameMap.get("box4-1.dat").add(HoleTypeT.Hole_Rect);
holeCandidatePartNameMap.put("stud4o.dat", new ArrayList<HoleTypeT>());
holeCandidatePartNameMap.get("stud4o.dat").add(HoleTypeT.Hole_Circle);
holeCandidatePartNameMap.put("stud4.dat", new ArrayList<HoleTypeT>());
holeCandidatePartNameMap.get("stud4.dat").add(HoleTypeT.Hole_Circle);
holeCandidatePartNameMap.put("stud4a.dat", new ArrayList<HoleTypeT>());
holeCandidatePartNameMap.get("stud4a.dat").add(HoleTypeT.Hole_Circle);
holeCandidatePartNameMap
.put("stud4f2n.dat", new ArrayList<HoleTypeT>());
holeCandidatePartNameMap.get("stud4f2n.dat").add(HoleTypeT.Hole_Circle);
studCandidatePartNameMap.put("stud.dat", new ArrayList<StudTypeT>());
studCandidatePartNameMap.get("stud.dat").add(StudTypeT.Stud);
studCandidatePartNameMap.put("stud2.dat", new ArrayList<StudTypeT>());
studCandidatePartNameMap.get("stud2.dat").add(StudTypeT.Stud);
studCandidatePartNameMap.put("studel.dat", new ArrayList<StudTypeT>());
studCandidatePartNameMap.get("studel.dat").add(StudTypeT.Stud);
studCandidatePartNameMap.put("stud2a.dat", new ArrayList<StudTypeT>());
studCandidatePartNameMap.get("stud2a.dat").add(StudTypeT.Stud);
studCandidatePartNameMap.put("4ring1.dat", new ArrayList<StudTypeT>());
studCandidatePartNameMap.get("4ring1.dat").add(StudTypeT.Stud);
studCandidatePartNameMap.put("stud10.dat", new ArrayList<StudTypeT>());
studCandidatePartNameMap.get("stud10.dat").add(
StudTypeT.Stud_RoundingBottom);
}
private void appendTransformMatrixInfo(StringBuilder strBuilder,
Matrix4 transformMatrix) {
for (int column = 0; column < 3; column++)
for (int row = 0; row < 3; row++) {
strBuilder.append(" ");
strBuilder.append(transformMatrix.element[column][row]);
}
for (int row = 0; row < 3; row++) {
strBuilder.append(" ");
strBuilder.append(transformMatrix.element[3][row]);
}
}
private boolean checkIsStud(String connName, Matrix4 transformMatrix) {
if (connName.toLowerCase().equals("4-4ring1.dat")) {
float sizes[] = new float[3];
for (int column = 0; column < 3; column++) {
float size = 0;
for (int row = 0; row < 3; row++) {
size += transformMatrix.element[column][row]
* transformMatrix.element[column][row];
}
size = (float) Math.sqrt(size);
sizes[column] = size;
}
if (MatrixMath.compareFloat(sizes[0], 5.0f) == 0
&& MatrixMath.compareFloat(sizes[2], 5.0f) == 0)
return true;
// System.out.println("need more check");
// System.out.println(transformMatrix);
} else
return true;
return false;
}
public void deleteConnFile(String partName) {
File file = new File(ConnectivityLibrary.ConnectivityFilesPath
+ LDrawUtilities.excludeExtensionFromPartName(partName)
+ ".conn");
if (file.exists())
file.delete();
}
public void getHoleInfo(String partName) {
LDrawPart part = new LDrawPart();
part.initWithPartName(partName, new Vector3f());
if (part.isPartDataExist() == false)
return;
// System.out.println("########" + partName + "#########");
LDrawModel model;
// part.setCacheModel(model);
part.resolvePart();
model = part.getCacheModel();
ArrayList<LDrawDirective> directives = new ArrayList<LDrawDirective>();
ArrayList<LDrawPart> candidateForHole = new ArrayList<LDrawPart>();
if (model == null)
return;
directives.addAll(model.steps());
while (directives.size() != 0) {
LDrawDirective directive = directives.remove(0);
if (directive instanceof LDrawPart) {
LDrawPart tempPart = (LDrawPart) directive;
String tempPartName = tempPart.displayName().toLowerCase();
Box3 bounding = tempPart.boundingBox3();
Vector3f sizeVector = bounding.getMax().sub(bounding.getMin());
if (sizeVector.dot(sizeVector) < 200)
continue;
// System.out.println(tempPartName);
if (holeCandidatePartNameMap.keySet().contains(tempPartName))
candidateForHole.add(tempPart);
else {
tempPart.setCacheModel(PartLibrary.sharedPartLibrary()
.readModelAtPath(
LDrawPaths.sharedPaths().pathForPartName(
tempPart.displayName()), new DispatchGroup(),
null, false));
if (tempPart.isConnectivityInfoExist()) {
writeConnInfo(partName, tempPart);
} else if (tempPart.getCacheModel() != null) {
directives.addAll(tempPart.getCacheModel().steps());
}
}
} else if (directive instanceof LDrawFile) {
LDrawFile file = (LDrawFile) directive;
if (file.activeModel() != null)
directives.addAll(file.activeModel().steps());
} else if (directive instanceof LDrawStep) {
LDrawStep step = (LDrawStep) directive;
directives.addAll(step.subdirectives());
}
}
// System.out.println("Candidate Directive For Hole");
for (LDrawPart targetPart : candidateForHole) {
String targetPartName = targetPart.displayName().toLowerCase();
Matrix4 transformMatrix = null;
HoleTypeT holeType = null;
for (HoleTypeT holeTypeTemp : holeCandidatePartNameMap
.get(targetPartName)) {
// System.out.println(targetPartName + ": " + holeTypeTemp);
transformMatrix = getHoleTransform(targetPart, holeTypeTemp,
part);
if (transformMatrix == null)
break;
holeType = holeTypeTemp;
// System.out.println("Projected Transform");
// System.out.println(transformMatrix);
for (int column = 0; column < 3; column++) {
float size = 0;
for (int row = 0; row < 3; row++) {
size += transformMatrix.element[column][row]
* transformMatrix.element[column][row];
}
size = (float) Math.sqrt(size);
for (int row = 0; row < 3; row++) {
transformMatrix.element[column][row] /= size;
}
}
// System.out.println("Normalized Transform");
// System.out.println(transformMatrix);
if (holeType != null) {
writeHoleInfo(partName, targetPart.displayName(), holeType,
transformMatrix);
}
}
}
}
private Matrix4 getHoleTransform(LDrawDirective targetDirective,
HoleTypeT holeType, LDrawPart parentPart) {
if (parentPart.getCacheModel() == null)
return null;
LDrawModel parentModel = parentPart.getCacheModel();
for (LDrawStep step : parentModel.steps()) {
for (LDrawDirective directive : step.subdirectives()) {
if (directive == targetDirective) {
if (directive instanceof LDrawPart) {
LDrawPart targetPart = (LDrawPart) targetDirective;
Matrix4 transformMatrix = targetPart
.transformationMatrix();
switch (holeType) {
case Hole_Circle: {
float sizes[] = new float[3];
for (int column = 0; column < 3; column++) {
float size = 0;
for (int row = 0; row < 3; row++) {
size += transformMatrix.element[column][row]
* transformMatrix.element[column][row];
}
size = (float) Math.sqrt(size);
sizes[column] = size;
}
// System.out.println(sizes[0] + ", " + sizes[1]
// + ", " + sizes[2]);
// System.out.println(targetPart.displayName());
// System.out.println(transformMatrix);
Vector3f offset = new Vector3f(-10, -sizes[1] * 4,
10);
Matrix4 rotationMatrix = new Matrix4(
transformMatrix);
for (int column = 0; column < 3; column++)
for (int row = 0; row < 3; row++)
rotationMatrix.element[column][row] /= sizes[column];
offset = MatrixMath.V3RotateByTransformMatrix(
offset, rotationMatrix);
transformMatrix.translate(offset.x, offset.y,
offset.z);
Matrix4 yInverse = Matrix4.getIdentityMatrix4();
yInverse.element[1][1] *= -1;
transformMatrix = Matrix4.multiply(yInverse,
transformMatrix);
return transformMatrix;
}
case Hole_Rect: {
float sizes[] = new float[3];
for (int column = 0; column < 3; column++) {
float size = 0;
for (int row = 0; row < 3; row++) {
size += transformMatrix.element[column][row]
* transformMatrix.element[column][row];
}
size = (float) Math.sqrt(size);
sizes[column] = size;
}
float x = sizes[0];
float z = sizes[2];
// System.out.println(targetPart.displayName());
// System.out.println(transformMatrix);
if (MatrixMath.compareFloat(x % 10, 6) != 0
|| MatrixMath.compareFloat(z % 10, 6) != 0)
return null;
Vector3f offset = new Vector3f(-(x + 4), 0, (z + 4));
holeType.setSize((Math.round(x + 4) / 10),
Math.round((z + 4) / 10));
Matrix4 rotationMatrix = new Matrix4(
transformMatrix);
for (int column = 0; column < 3; column++)
for (int row = 0; row < 3; row++)
rotationMatrix.element[column][row] /= sizes[column];
offset = MatrixMath.V3RotateByTransformMatrix(
offset, rotationMatrix);
Matrix4 yInverse = Matrix4.getIdentityMatrix4();
yInverse.element[1][1] *= -1;
transformMatrix = Matrix4.multiply(yInverse,
transformMatrix);
transformMatrix.translate(offset.x, offset.y,
offset.z);
// transformMatrix =
// MatrixMath.Matrix4Multiply(transformMatrix,
// parentPart.transformationMatrix());
return transformMatrix;
}
}
}
} else {
if (directive instanceof LDrawPart) {
LDrawPart part = (LDrawPart) directive;
Matrix4 transformMatrix = null;
transformMatrix = getHoleTransform(targetDirective,
holeType, part);
if (transformMatrix != null) {
// System.out.println("Parent's Transform Matrix: "
// + part.displayName());
// System.out.println(part.transformationMatrix());
transformMatrix = Matrix4.multiply(transformMatrix,
part.transformationMatrix());
return transformMatrix;
}
}
}
}
}
return null;
}
public void getStudInfo(String partName) {
LDrawPart part = new LDrawPart();
part.initWithPartName(partName, new Vector3f());
if (part.isPartDataExist() == false)
return;
LDrawModel model;
part.resolvePart();
// LDrawModel model = PartLibrary.sharedPartLibrary()
// .readModelAtPath(
// LDrawPaths.sharedPaths().pathForPartName(
// partName), false,
// null, false);
// part.setCacheModel(model);
model = part.getCacheModel();
ArrayList<LDrawDirective> directives = new ArrayList<LDrawDirective>();
ArrayList<LDrawPart> candidateForStud = new ArrayList<LDrawPart>();
if (model == null)
return;
directives.addAll(model.steps());
while (directives.size() != 0) {
LDrawDirective directive = directives.remove(0);
if (directive instanceof LDrawPart) {
LDrawPart tempPart = (LDrawPart) directive;
Box3 bounding = tempPart.boundingBox3();
Vector3f sizeVector = bounding.getMax().sub(bounding.getMin());
if (sizeVector.dot(sizeVector) < 100)
continue;
String tempPartName = tempPart.displayName().toLowerCase();
// System.out.println(tempPartName);
if (studCandidatePartNameMap.keySet().contains(tempPartName)) {
candidateForStud.add(tempPart);
} else {
tempPart.setCacheModel(PartLibrary.sharedPartLibrary()
.readModelAtPath(
LDrawPaths.sharedPaths().pathForPartName(
tempPart.displayName()), new DispatchGroup(),
null, false));
if (tempPart.isConnectivityInfoExist()) {
writeConnInfo(partName, tempPart);
} else if (tempPart.getCacheModel() != null) {
directives.addAll(tempPart.getCacheModel().steps());
}
}
} else if (directive instanceof LDrawFile) {
LDrawFile file = (LDrawFile) directive;
if (file.activeModel() != null)
directives.addAll(file.activeModel().steps());
} else if (directive instanceof LDrawStep) {
LDrawStep step = (LDrawStep) directive;
directives.addAll(step.subdirectives());
}
}
for (LDrawPart targetPart : candidateForStud) {
String targetPartName = targetPart.displayName().toLowerCase();
Matrix4 transformMatrix = getStudTransform(targetPart, part);
if (checkIsStud(targetPartName, transformMatrix) == true) {
for (int column = 0; column < 3; column++) {
float size = 0;
for (int row = 0; row < 3; row++) {
size += transformMatrix.element[column][row]
* transformMatrix.element[column][row];
}
size = (float) Math.sqrt(size);
for (int row = 0; row < 3; row++)
transformMatrix.element[column][row] /= size;
}
for (StudTypeT studType : studCandidatePartNameMap
.get(targetPartName)) {
writeStudInfo(partName, targetPartName, studType,
transformMatrix);
}
}
}
}
private Matrix4 getStudTransform(LDrawDirective targetDirective,
LDrawPart parentPart) {
if (parentPart.getCacheModel() == null)
return null;
LDrawModel parentModel = parentPart.getCacheModel();
for (LDrawStep step : parentModel.steps()) {
for (LDrawDirective directive : step.subdirectives()) {
if (directive == targetDirective) {
if (directive instanceof LDrawPart) {
LDrawPart targetPart = (LDrawPart) targetDirective;
Matrix4 transformMatrix = targetPart
.transformationMatrix();
Vector3f offset = new Vector3f(-10, 0, 10);
Matrix4 rotationMatrix = new Matrix4(transformMatrix);
for (int column = 0; column < 3; column++) {
float size = 0;
for (int row = 0; row < 3; row++) {
size += transformMatrix.element[column][row]
* transformMatrix.element[column][row];
}
size = (float) Math.sqrt(size);
for (int row = 0; row < 3; row++)
rotationMatrix.element[column][row] /= size;
}
offset = MatrixMath.V3RotateByTransformMatrix(offset,
rotationMatrix);
transformMatrix.translate(offset.x, offset.y, offset.z);
return transformMatrix;
}
} else {
if (directive instanceof LDrawPart) {
Matrix4 transformMatrix = null;
transformMatrix = getStudTransform(targetDirective,
(LDrawPart) directive);
if (transformMatrix != null) {
LDrawPart part = (LDrawPart) directive;
// System.out.println("Parent's Transform Matrix: "
// + part.displayName());
// System.out.println(part.transformationMatrix());
transformMatrix = Matrix4.multiply(transformMatrix,
part.transformationMatrix());
return transformMatrix;
}
}
}
}
}
return null;
}
private void writeConnInfo(String partName, LDrawPart tempPart) {
StringBuilder strBuilder = new StringBuilder();
ArrayList<Connectivity> connList = tempPart.getConnectivityList();
if (connList == null)
return;
for (Connectivity conn : connList) {
strBuilder.append(conn.toString());
strBuilder.append("\r\n");
}
File file = new File(ConnectivityLibrary.ConnectivityFilesPath
+ LDrawUtilities.excludeExtensionFromPartName(partName)
+ ".conn");
try {
FileWriter fw = null;
if (file.exists())
fw = new FileWriter(file, true);
else
fw = new FileWriter(file, false);
fw.write(strBuilder.toString());
fw.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void writeHoleInfo(String partName, String connName,
HoleTypeT holeType, Matrix4 transformMatrix) {
StringBuilder strBuilder = new StringBuilder();
strBuilder.append("2 22");
appendTransformMatrixInfo(strBuilder, transformMatrix);
switch (holeType) {
case Hole_Rect:
strBuilder.append(" ");
strBuilder.append(2 * holeType.getHeight());
strBuilder.append(" ");
strBuilder.append(2 * holeType.getWidth());
strBuilder.append(" ");
for (int height = 0; height < holeType.getHeight() * 2 + 1; height++)
for (int width = 0; width < holeType.getWidth() * 2 + 1; width++) {
if (height == 0 || height == holeType.getHeight() * 2)
strBuilder.append("22:1:1,");
else if (width == 0 || width == holeType.getWidth() * 2)
strBuilder.append("22:1:1,");
else if (height % 2 == 1 && width % 2 == 1)
strBuilder.append("17:4:1,");
else
strBuilder.append("22:1:1,");
}
break;
case Hole_Circle:
strBuilder
.append(" 2 2 29:0,29:0,29:0,29:0,17:4:1,29:0,29:0,29:0,29:0,");
break;
default:
return;
}
strBuilder.append(" ");
strBuilder.append(connName);
strBuilder.append("\r\n");
// System.out.println(strBuilder.toString());
File file = new File(ConnectivityLibrary.ConnectivityFilesPath
+ LDrawUtilities.excludeExtensionFromPartName(partName)
+ ".conn");
try {
FileWriter fw = new FileWriter(file, true);
fw.write(strBuilder.toString());
fw.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void writeStudInfo(String partName, String connName,
StudTypeT studType, Matrix4 transformMatrix) {
StringBuilder strBuilder = new StringBuilder();
strBuilder.append("3 23");
appendTransformMatrixInfo(strBuilder, transformMatrix);
switch (studType) {
case Stud:
strBuilder
.append(" 2 2 18:1:1,23:4:1,18:1:1,23:4:1,0:4:1,23:4:1,18:1:1,23:4:1,18:1:1,");
break;
case Stud_RoundingBottom:
strBuilder
.append(" 2 2 29:0,29:0,29:0,29:0,0:4:1,29:0,29:0,29:0,29:0,");
break;
}
strBuilder.append(" ");
strBuilder.append(connName);
strBuilder.append("\r\n");
// System.out.println(transformMatrix);
// System.out.println(strBuilder.toString());
File file = new File(ConnectivityLibrary.ConnectivityFilesPath
+ LDrawUtilities.excludeExtensionFromPartName(partName)
+ ".conn");
try {
FileWriter fw = new FileWriter(file, true);
fw.write(strBuilder.toString());
fw.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}